let path = require('path')
let fs = require('fs')
let express = require('express')
let utils = require('../utils')

/**
 * req res
 * res 写流
 */

let app = express()
let {
  readFile,
  readFiles,
  promisify,
  openBrowser
} = utils
let exists = promisify(fs.exists)
let lstat = promisify(fs.lstat)
let readlink = promisify(fs.readlink)
let cwd = process.cwd()
let port = 5000

app.set('views', './src/views')
app.set('view engine', 'ejs')

app.use(async (req, res, next) => {
  let locals = {}
  let pathname = req.path
  let filename = path.join(cwd, pathname)
  if (pathname) {
    locals.pathname = pathname
  }
  let isExist = await exists(filename)
  if (!isExist) {
    return handleNotFound(req, res)
  }
  let file = await lstat(filename)
  if (!file) {
    return handleNotFound(req, res)
  }
  locals.isFile = file.isFile()
  locals.isDirectory = file.isDirectory()
  let isSymbolicLink = file.isSymbolicLink()
  if (isSymbolicLink) {
    locals.isSymbolicLink = isSymbolicLink
    let link = await readlink(filename)
    filename = path.join(cwd, path.dirname(pathname), link)
  }
  if (filename) {
    locals.filename = filename
  }
  res.locals = locals
  next()
})

app.get('/', handleRenderFiles)
app.get('*', handler).listen({ port }, () => {
  openBrowser(`http://localhost:${port}`)
})

async function handler(req, res) {
  let { isFile, isDirectory, isSymbolicLink } = res.locals
  if (isDirectory || isSymbolicLink) {
    handleRenderFiles(req, res)
  } else if (isFile) {
    handleRenderFile(req, res)
  }
}

async function handleRenderFile(req, res) {
  let { pathname, filename } = res.locals
  let extname = path.extname(pathname) || 'text/plain'
  res.type(extname)
  return res.send(await readFile(filename))
}

async function handleRenderFiles(req, res) {
  let { pathname, filename } = res.locals
  let list = await getDirectoryFile(filename, { pathname })
  res.render('index', { list })
}

function handleNotFound(req, res) {
  res.render('404')
}

async function getDirectoryFile(directory, { pathname }) {
  let list = await readFiles(directory)
  list = list.map(item => {
    return {
      ...item,
      href: path.join(pathname, item.name)
    }
  })
  if (pathname && pathname !== '/') {
    // 是子文件夹
    list = [{ name: '..', href: path.dirname(pathname) }].concat(list)
  }
  return list
}
